﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;

namespace Aspire
{
    /// <summary>
    /// Represents a downloaded Xap, including the bytes that were downloaded, the assemblies that were loaded, and a parsed
    /// version of the AppManifest.
    /// </summary>
    public class Xap : DependencyObject
    {
        internal Xap(Manifest d, IEnumerable<Assembly> assemblies, IDictionary<Assembly, byte[]> streamMapping)
        {
            this.Manifest = d;
            this.Assemblies = new List<Assembly>(assemblies).AsReadOnly();
            this.streamMapping = streamMapping;
        }

        /// <summary>
        /// Gets the parsed AppManifest of the Xap.
        /// </summary>
        public Manifest Manifest { get; private set; }

        /// <summary>
        /// Gets the set of Assemblies (including "cached assemblies") found within the Xap.
        /// </summary>
        public IEnumerable<Assembly> Assemblies { get; private set; }
        private IDictionary<Assembly, byte[]> streamMapping;

        /// <summary>
        /// Gets the stream that was used to load the assembly into the AppDomain.  Use this for serialization purposes.
        /// </summary>
        /// <param name="asm">The assembly whose stream is being requested.</param>
        /// <returns>The stream that was used to load the assembly.</returns>
        public Stream GetStream(Assembly asm)
        {
            return new MemoryStream(streamMapping[asm]);
        }

        /// <summary>
        /// Gets the entry point assembly (indicated by the manifest) for the Xap.
        /// </summary>
        public Assembly EntryPointAssembly
        {
            get
            {
                return (from asm in Assemblies
                        where asm.FullName.Split(',')[0].Equals(Manifest.EntryPointAssembly)
                        select asm).SingleOrDefault();
            }
        }

        /// <summary>
        /// Gets the entry point type (indicated by the manifest) for the Xap.
        /// </summary>
        public Type EntryPointType
        {
            get
            {
                return EntryPointAssembly.GetType(Manifest.EntryPointType);
            }
        }
    }
}
